<!DOCTYPE html>
<html>

<head>
    <title>opentype.js glyph inspector</title>
    <meta charset="utf-8">
    <script src="https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js"></script>
    <style type="text/css">
        .icon-wrap canvas {
            margin-right: 10px;
            margin-bottom: 10px;
            border: 1px solid #E8E9EC;
        }

        .download-cls {
            display: inline-block;
        }
    </style>
</head>

<body>
    <div class="container">
        <div>
            <input id="file" type="file">
            <div class="download-cls" onclick="onDownSvg()">下载当页icon为svg</div>
        </div>
        <span class="info" id="font-name"></span>
        <div id="message"></div>
        <div class="icon-wrap">
            <span id="pagination"></span>
            <br>
            <div id="glyph-list-end"></div>
        </div>
    </div>


    <script>
        var cellCount = 100,
            cellWidth = 80,
            cellHeight = 100,
            cellMarginTop = 1,
            cellMarginBottom = 40,
            cellMarginLeftRight = 1,
            glyphMargin = 5,
            pixelRatio = window.devicePixelRatio || 1;

        var pageSelected, font, fontScale, fontSize, fontBaseline, glyphScale, glyphSize, glyphBaseline;

        function showErrorMessage(message) {
            var el = document.getElementById('message');
            if (!message || message.trim().length === 0) {
                el.style.display = 'none';
            } else {
                el.style.display = 'block';
            }
            el.innerHTML = message;
        }

        function formatUnicode(unicode) {
            unicode = unicode.toString(16);
            if (unicode.length > 4) {
                return ("000000" + unicode.toUpperCase()).substr(-6)
            } else {
                return ("0000" + unicode.toUpperCase()).substr(-4)
            }
        }
        function downFun(filename, content) {
            // 创建a标签
            var eleLink = document.createElement('a')
            // 设置a标签 download 属性，以及文件名
            eleLink.download = filename + ".svg"
            // a标签不显示
            eleLink.style.display = 'none'
            // 获取字符内容，转为blob地址
            var blob = new Blob([content])
            // blob地址转为URL
            eleLink.href = URL.createObjectURL(blob)
            // a标签添加到body
            document.body.appendChild(eleLink)
            // 触发a标签点击事件，触发下载
            eleLink.click()
            // a标签从body移除
            document.body.removeChild(eleLink)
        }
        function onDownSvg() {
            for (var i = 0; i < font.glyphs.length; i++) {
                downGlyphData(i)
            }
        }

        function downGlyphData(glyphIndex) {
            if (glyphIndex < 0) {
                return;
            }
            var glyph = font.glyphs.get(glyphIndex)
            if (glyph.name != '') {
                var style = ''
                if (glyph.yMin <= 0) {
                    // style='transform: rotateX(180deg) rotateY(180deg)'
                    style += "style='transform: rotateX(180deg)'"
                }
                var tempSvg = ""
                tempSvg += '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
                tempSvg += '<svg width="100%" height="100%" ' + style + ' version="1.1" xmlns="http://www.w3.org/2000/svg">'
                tempSvg += glyph.path.toSVG()
                tempSvg += '</svg>'
                downFun(glyph.name, tempSvg)
            }
        }

        var arrowLength = 10,
            arrowAperture = 4;

        function drawArrow(ctx, x1, y1, x2, y2) {
            var dx = x2 - x1,
                dy = y2 - y1,
                segmentLength = Math.sqrt(dx * dx + dy * dy),
                unitx = dx / segmentLength,
                unity = dy / segmentLength,
                basex = x2 - arrowLength * unitx,
                basey = y2 - arrowLength * unity,
                normalx = arrowAperture * unity,
                normaly = -arrowAperture * unitx;
            ctx.beginPath();
            ctx.moveTo(x2, y2);
            ctx.lineTo(basex + normalx, basey + normaly);
            ctx.lineTo(basex - normalx, basey - normaly);
            ctx.lineTo(x2, y2);
            ctx.closePath();
            ctx.fill();
        }

        function renderGlyphItem(canvas, glyphIndex) {
            var cellMarkSize = 4;
            var ctx = canvas.getContext('2d');
            ctx.clearRect(0, 0, cellWidth, cellHeight);
            if (glyphIndex >= font.numGlyphs) return;

            ctx.fillStyle = '#606060';
            ctx.font = '9px sans-serif';
            var glyph = font.glyphs.get(glyphIndex),
                glyphWidth = glyph.advanceWidth * fontScale,
                xmin = (cellWidth - glyphWidth) / 2,
                xmax = (cellWidth + glyphWidth) / 2,
                x0 = xmin;
            ctx.fillText(glyph.name, 4, cellHeight - 30);
            if (glyph.unicodes.length > 0) {
                ctx.fillText(formatUnicode(glyph.unicode), 4, cellHeight - 10);
            }
            ctx.fillStyle = '#000000';
            glyph.draw(ctx, x0, fontBaseline, fontSize);
        }

        function displayGlyphPage(pageNum) {
            pageSelected = pageNum;
            document.getElementById('p' + pageNum).className = 'page-selected';
            var firstGlyph = pageNum * cellCount;
            for (var i = 0; i < cellCount; i++) {
                renderGlyphItem(document.getElementById('g' + i), firstGlyph + i);
            }
        }

        function pageSelect(event) {
            document.getElementsByClassName('page-selected')[0].className = '';
            displayGlyphPage(+event.target.id.substr(1));
        }
        function onFontLoaded(font) {
            window.font = font;
            var w = cellWidth - cellMarginLeftRight * 2,
                h = cellHeight - cellMarginTop - cellMarginBottom,
                head = font.tables.head,
                maxHeight = head.yMax - head.yMin;
            fontScale = Math.min(w / (head.xMax - head.xMin), h / maxHeight);
            fontSize = fontScale * font.unitsPerEm;
            fontBaseline = cellMarginTop + h * head.yMax / maxHeight;

            var pagination = document.getElementById("pagination");
            pagination.innerHTML = '';
            var fragment = document.createDocumentFragment();
            var numPages = Math.ceil(font.numGlyphs / cellCount);
            for (var i = 0; i < numPages; i++) {
                var link = document.createElement('span');
                var lastIndex = Math.min(font.numGlyphs - 1, (i + 1) * cellCount - 1);
                link.textContent = i * cellCount + '-' + lastIndex;
                link.id = 'p' + i;
                link.addEventListener('click', pageSelect, false);
                fragment.appendChild(link);
                fragment.appendChild(document.createTextNode(' '));
            }
            pagination.appendChild(fragment);

            displayGlyphPage(0);
            downGlyphData(-1);
        }

        function onReadFile(e) {
            document.getElementById('font-name').innerHTML = '';
            var file = e.target.files[0];
            var reader = new FileReader();
            reader.onload = function (e) {
                try {
                    font = opentype.parse(e.target.result, { lowMemory: true });
                    showErrorMessage('');
                    onFontLoaded(font);
                } catch (err) {
                    showErrorMessage(err.toString());
                    if (err.stack) console.log(err.stack);
                    throw (err);
                }
            };
            reader.onerror = function (err) {
                showErrorMessage(err.toString());
            };

            reader.readAsArrayBuffer(file);
        }

        function cellSelect(event) {
            if (!font) return;
            var firstGlyphIndex = pageSelected * cellCount,
                cellIndex = +event.target.id.substr(1),
                glyphIndex = firstGlyphIndex + cellIndex;
            if (glyphIndex < font.numGlyphs) {
                downGlyphData(glyphIndex);
            }
        }

        function prepareGlyphList() {
            var marker = document.getElementById('glyph-list-end'),
                parent = marker.parentElement;
            for (var i = 0; i < cellCount; i++) {
                var canvas = document.createElement('canvas');
                canvas.width = cellWidth;
                canvas.height = cellHeight;
                canvas.className = 'item';
                canvas.id = 'g' + i;
                canvas.addEventListener('click', cellSelect, false);
                parent.insertBefore(canvas, marker);
            }
        }
        var fileButton = document.getElementById('file');
        fileButton.addEventListener('change', onReadFile, false);
        prepareGlyphList();
    </script>
</body>

</html>